#include "my_sever.h"

my_sever::my_sever(int num):Tcpserver(num)
{
    this->db=new DB("192.168.100.128","root","1","BrainStorm");
    initrankMap();

}

void my_sever::readEvent(Tcpsocket *s)
{
    qDebug()<<"从客户端读\n"<<"ip地址:"<<s->getip()<<"端口号:"<<s->getPort()<<"\n";

    char buf[1024] = {0};
    json j;//收到的json数据
    while (1)
    {
        int len = 0;
        // 循环读取4字节长度
        int recvLen = 0;
        while (recvLen < sizeof(len)) {
            int ret = s->read((char*)&len + recvLen, sizeof(len) - recvLen);
            if (ret <= 0) return; // 连接关闭或出错
            recvLen += ret;
        }

        // 如果跨平台，建议：
        //        len = ntohl(len);

        if (len <= 0 || len > sizeof(buf)) {
            return; // 防止非法长度
        }

        // 循环读取数据内容
        int received = 0;
        while (received < len) {
            int ret = s->read(buf + received, len - received);
            if (ret <= 0) return;
            received += ret;
        }

        // 转 JSON
        try {
            j = json::parse(std::string(buf, len));
            std::cout << "收到 cmd: " << j["cmd"] << std::endl;
            std::cout << "用户名: " << j["userName"] << std::endl;
            std::cout << "密码: " << j["passwd"] << std::endl;
        }
        catch (const json::parse_error &e) {
            std::cerr << "JSON 解析失败: " << e.what() << std::endl;
        }
        switch ((int)j["cmd"]) {
        case REGISTER :
            this->Register(s,j);
            break;
        case LOGIN:
            this->Login(s,j);
            break;
        case SINGLE_GETQ:
            this->singleGetQ(s,j);
            break;
        case RANK:
            std::cout<<"当前等待人数:"<<rankQueue.size()<<"\n"<<endl;
            this->Rank(s,j);
            break;
        case ANSWER:
            this->rankAnswerQ(s,j);
            break;
        case RANKRESULT:
            this->rankResult(s,j);
            break;
        default:
            break;

        }
    }
}

void my_sever::writeEvent(Tcpsocket *s)
{

}

void my_sever::closeEvent(Tcpsocket *s, short what)
{   //将用户从等待队列删除

    {
        std::unique_lock<std::mutex>lock(rankLock);
        int rank=users[s->getuserName()]->getRank();
        auto it=rankQueue.find(rank);
        if(it!=rankQueue.end())
        {
            rankQueue.erase(it);
        }
    }

    auto item=users.begin();
    while(item!=users.end())
    {
        if(item->second->getSocket()==s)
        {

            qDebug()<<"客户端退出\n"<<"名字:"<<item->second->getuserName().c_str()<<"\n";
            delete item->second;
            users.erase(item);
            break;

        }
        else
        {item++;}
    }
}

void my_sever::connectEvent(Tcpsocket *s)
{
    qDebug()<<"有客户端链接\n"<<"ip地址:"<<s->getip()<<"端口号:"<<s->getPort();
}

void my_sever::initrankMap()
{
    char buf[1024] = {0};
    int rank = 0;
    int num = 0;
    for(int i = 0; i < 100; i++) {
        if(i < 9) {  // 青铜段位：0-8 (9个等级)
            rank = i / 3;  // 0-2
            num = i % 3;   // 0-2
            sprintf(buf, "青铜%d %d颗星", 3 - rank, num + 1);
        }
        else if(i < 18) {  // 白银段位：9-17 (9个等级)
            rank = (i - 9) / 3;  // 0-2
            num = (i - 9) % 3;   // 0-2
            sprintf(buf, "白银%d %d颗星", 3 - rank, num + 1);
        }
        else if(i < 34) {  // 黄金段位：18-33 (16个等级)
            rank = (i - 18) / 4;  // 0-3
            num = (i - 18) % 4;   // 0-3
            sprintf(buf, "黄金%d %d颗星", 4 - rank, num + 1);
        }
        else if(i < 50) {  // 铂金段位：34-49 (16个等级)
            rank = (i - 34) / 4;  // 0-3
            num = (i - 34) % 4;   // 0-3
            sprintf(buf, "铂金%d %d颗星", 4 - rank, num + 1);
        }
        else if(i < 75) {  // 钻石段位：50-74 (25个等级)
            rank = (i - 50) / 5;  // 0-4
            num = (i - 50) % 5;   // 0-4
            sprintf(buf, "钻石%d %d颗星", 5 - rank, num + 1);
        }
        else {  // 星耀段位：75-99 (25个等级)
            rank = (i - 75) / 5;  // 0-4
            num = (i - 75) % 5;   // 0-4
            sprintf(buf, "星耀%d %d颗星", 5 - rank, num + 1);
        }
        rankMap.insert(make_pair(i, buf));
    }
}

void my_sever::Register(Tcpsocket *s, json &j)
{
    string userName=j["userName"];
    string passwd=j["passwd"];
    char sql[1024]={0};
    //检查用户是否存在
    int result =OK;
    sprintf(sql,"select * from user where name='%s' and passwd='%s'",
            userName.c_str(),passwd.c_str());
    qDebug()<<" 执行搜索\n";
    json outjson;
    bool ret=db->db_select(sql,outjson);
    if(!ret)
    {
        result=ERROR;
        cout<<" 查询未知错误（db_select）\n";
    }
    if(outjson.is_array() && !outjson.empty())
    {
        result=USEREXIST;
    }
    else
    {

        memset(sql,0,sizeof(sql));
        sprintf(sql,"insert into user (name,passwd,`rank`) values('%s','%s',0)"
                ,userName.c_str(),passwd.c_str());
        bool ret2=db->db_exec(sql);
        if(!ret2)
        {
            result=ERROR;
            cout<<" 插入未知错误（db_exec）\n";
        }

    }
    json rejson;
    rejson["cmd"]=REGISTER;
    rejson["result"]=result;
    cout<<"回复消息\n"<<REGISTER<<"\n"<<result<<endl;
    this->writeData(s,rejson);
}

void my_sever::writeData(Tcpsocket *s, json &j)
{
    string data=j.dump();
    int len = data.size();

    // 2. 发送长度
    s->write((char*)&len, sizeof(len));
    cout<<"回复长度消息\n";
    // 3. 发送数据
    s->write((void*)data.c_str(), len);
    cout<<"回复数据消息\n";
}

void my_sever::Login(Tcpsocket *s, json &j)
{

    string userName=j["userName"];
    string passwd=j["passwd"];
    string rank;
    char sql[1024]={0};
    //检查用户是否注册过
    int result =OK;
    sprintf(sql,"select * from user where name='%s' and passwd='%s'",
            userName.c_str(),passwd.c_str());
    json outjson;
    bool ret=db->db_select(sql,outjson);
    if(!ret)
    {
        result=ERROR;
        cout<<" 查询未知错误（db_select）\n";
    }
    if(outjson.is_array() && !outjson.empty())//注册过
    {
        std::unique_lock<std::mutex>lock(userLock);
        if(users.find(userName)!=users.end())
        {
            result=USERLOGIN;
        }
        else
        {
            json firstUser = outjson[0];
            rank=firstUser["rank"].get<string>();
            int temprank=stoi(rank);
            cout<<"outjson[name] "<<firstUser["name"]<<"\n"<<temprank<<"\n";
            User* user = new User(firstUser["name"], firstUser["passwd"],temprank,s);
            users[userName] = user;
            s->setuserName(firstUser["name"].get<string>());
        }
    }
    else
        result=NAMEORPASSWD;

    json rejson;
    rejson["cmd"]=LOGIN;
    rejson["result"]=result;
    rejson["userName"]=userName;
    rejson["userRank"]=rankMap[stoi(rank)];
    //rank
    cout<<"回复消息\n"<<LOGIN<<"\n"<<result<<"\n"<<userName<<"\n"<<rank<<endl;
    this->writeData(s,rejson);
}

void my_sever::singleGetQ(Tcpsocket *s, json &)
{
    char sql[1024]={0};
    sprintf(sql,"select * from questions order by rand() limit %d",QUESTIONNUM);
    json j;//查到的数据
    int result=OK;
    bool ret=this->db->db_select(sql,j);
    if(!ret||j.size()<5)
    {
        result=ERROR;
        cout<<" 查询未知错误（db_select）\n";
    }
    json rejson;
    rejson["cmd"]=SINGLE_GETQ;
    rejson["result"]=result;
    rejson["question"]=j;
    cout<<"username:"<<s->getuserName()<<"...."<<s->getip()<<"...."<<s->getPort()<<"\n";
    cout<<"question:\n"<<j.dump()<<"\n";
    this->writeData(s,rejson);
}

void my_sever::rankAnswerQ(Tcpsocket *s, json &j)
{
    string enemyname=j["enemyName"];
    User*user=users[enemyname];

    json rejson;
    rejson["cmd"]=ANSWER;
    rejson["enemyscore"]=j["score"];
    rejson["questionId"]=j["questionId"];
    std::cout<<rejson.dump()<<std::endl;
    this->writeData(user->getSocket(),rejson);

}

void my_sever::rankResult(Tcpsocket *s, json &j)
{
    std::unique_lock<std::mutex>lock(userLock);
    User*user=users[s->getuserName()];
    int myscore=j["score"];
    int enemyscore=j["enemyscore"];
    if(myscore<enemyscore)
        user->setRank(user->getRank()-1);
    else if(myscore>enemyscore)
        user->setRank(user->getRank()+1);
    json rejson;
    rejson["cmd"]=RANKRESULT;
    rejson["newrank"]=rankMap[user->getRank()];
    std::cout<<rejson.dump()<<std::endl;
    this->writeData(user->getSocket(),rejson);
}

void my_sever::Rank(Tcpsocket *s, json &j)
{
    std::cout<<"当前等待人数:"<<rankQueue.size()<<"\n"<<endl;
    Tcpsocket*other=NULL;
    int rank=users[s->getuserName()]->getRank();//当前用户rank分
    std::unique_lock<std::mutex>lock(rankLock);
    std::cout<<"当前等待人数:"<<rankQueue.size()<<"\n"<<endl;
    //查找匹配的对手,同段位
    auto item=rankQueue.find(rank);
    if(item!=rankQueue.end())
    {
        other=item->second;
        rankQueue.erase(item);
    }
    else
    {
        for(int i=1;i<=5;i++)
        {   //差之为5
            auto item=rankQueue.find(rank+i);
            if(item!=rankQueue.end())
            {
                other=item->second;
                rankQueue.erase(item);
                break;
            }
            item=rankQueue.find(rank-i);
            if(item!=rankQueue.end())
            {
                other=item->second;
                rankQueue.erase(item);
                break;
            }
        }

    }
    if(other==NULL)
    {
        rankQueue.insert(make_pair(rank,s));
        std::cout<<"当前等待人数:"<<rankQueue.size()<<"\n"<<endl;
    }
    else//找到了
    {
        //开始对决
        startRank(s,other);

    }
}

void my_sever::startRank(Tcpsocket *first, Tcpsocket *second)
{
    char sql[1024]={0};
    sprintf(sql,"select * from questions order by rand() limit %d",QUESTIONNUM);
    json j;//查到的数据
    std::cout<<"当前等待人数: j"<<rankQueue.size()<<"\n"<<endl;
    int result=OK;
    bool ret=this->db->db_select(sql,j);

    if(!ret||j.size()<QUESTIONNUM)
    {
        result=ERROR;
        cout<<" 查询未知错误startRank（db_select）\n";
    }
    json rejson;
    rejson["cmd"]=RANK;
    rejson["result"]=result;
    rejson["question"]=j;
    //"enemyName":""
    //"enemyRank":"黄金1 1颗星"
    //"enemyScore":0
    //first user

    rejson["enemyName"]=second->getuserName();
    rejson["enemyRank"]=rankMap[users[second->getuserName()]->getRank()];
    this->writeData(first,rejson);
    std::cout<<"json 1:"<<rejson.dump()<<"\n"<<endl;
    //second user
    rejson["enemyName"]=first->getuserName();
    rejson["enemyRank"]=rankMap[users[first->getuserName()]->getRank()];
    this->writeData(second,rejson);
    std::cout<<"json 2:"<<rejson.dump()<<"\n"<<endl;
}








